function isObject(obj) {
  return obj && (typeof obj === 'object' || typeof obj === 'function')
}

function deepClone(target, hashMap = new WeakMap()) {
  if (!isObject(target)) return target
  let newObj = Array.isArray(target) ? [] : {}
  if (hashMap.has(target)) return hashMap.get(target)
  hashMap.set(target, newObj)
  Reflect.ownKeys(target).forEach(key => {
    if (isObject(target)) {
      newObj[key] = deepClone(target[key], hashMap)
    } else {
      newObj[key] = target[key]
    }
  })
  return newObj
}

let obj1 = {
  name: '123',
  sex: 1,
  fav: {
    a: 'sing',
    b: 'code'
  },
  sayHello: function () {
    console.log('hello');
  },
  arr: [1, 2, 3, 4, 5]
}
let obj2 = deepClone(obj1)
console.log(obj2);